<?php
#+------------------------------------------------------------------
#| 我曾七次鄙视自己的灵魂:
#| 第一次,当它本可进取时，却故作谦卑；
#| 第二次,当它空虚时，用爱欲来填充；
#| 第三次,在困难和容易之间，它选择了容易；
#| 第四次,它犯了错，却借由别人也会犯错来宽慰自己；
#| 第五次,它自由软弱，却把它认为是生命的坚韧；
#| 第六次,当它鄙夷一张丑恶的嘴脸时，却不知那正是自己面具中的一副；
#| 第七次,它侧身于生活的污泥中虽不甘心，却又畏首畏尾。
#+------------------------------------------------------------------
#| Author:Janmas Cromwell <janmas-cromwell@outlook.com>
#+------------------------------------------------------------------
namespace app\common\lib;

use think\Exception;
use think\facade\Cache;

class Identity
{

    /**
     * access_token缓存键名后缀
     */
    const ACCESS_TOKEN_KEY = 'ACCESS_TOKEN';

    /**
     * 刷新accessToken临时缓存键名后缀
     */
    const TEMP_ACCESS_TOKEN_KEY = 'TEMP_ACCESS_TOEKN';

    /**
     * 生成uuid
     * @param bool $short 是否为短uuid
     */
    public static function uuid(bool $short = false)
    {
        //xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx
        //8-4-4-4-12
        $chars = md5(uniqid(mt_rand(), true));
        $uuid = substr($chars, 0, 8) . '-';
        $uuid .= substr($chars, 8, 4) . '-';
        $uuid .= substr($chars, 12, 4) . '-';
        $uuid .= substr($chars, 16, 4) . '-';
        $uuid .= substr($chars, 20, 12);
        if (!$short) {
            return $uuid;
        }

        $noLineUuid = str_replace('-', '', $uuid);
        return base_convert($noLineUuid, 16, 36);
    }

    /**
     * 生成appid
     */
    public static function appid()
    {
        return uniqid(mt_rand(), false);
    }

    /**
     * 生成secret
     * @param string $appid 用户的appid
     */
    public static function secret(string $appid = '')
    {
        $uuid = self::uuid(true);
        $tmp = array_merge(str_split($appid), str_split($uuid));
        shuffle($tmp);
        return implode($tmp);
    }

    /**
     * 根据appid，secret获取access_token
     * @param string $appid
     * @param string $secret
     */
    public static function accessToken(string $appid, string $secret, bool $force = false)
    {
        if (Cache::has($appid . self::ACCESS_TOKEN_KEY) && !$force) {
            $accessToekn = Cache::get($appid . self::ACCESS_TOKEN_KEY);
            return $accessToekn['access_token'];
        }
        $appidCharsList = str_split($appid);
        $secretCharsList = str_split($secret);
        $uniqid = uniqid();
        $appidCharsList = array_pad(
            $appidCharsList,
            strlen($secret),
            $uniqid[rand(0, strlen($uniqid) - 1)]
        );
        $tmp = array_merge($secretCharsList, $appidCharsList);
        shuffle($tmp);
        $accessToekn = implode('', $tmp) . $uniqid;
        Cache::set($appid . self::ACCESS_TOKEN_KEY, ['access_token' => $accessToekn, 'time' => time()], 7200);
        return $accessToekn;
    }

    /**
     * 刷新access_token
     * @param string $appid
     * @param string $secret
     * @param string $accessToken
     */
    public static function refreshAccessToken(string $appid, string $secret, string $accessToken)
    {
        if (!Cache::has($appid . self::ACCESS_TOKEN_KEY)) {
            throw new Exception('access_token已过期，请重新获取');
        }

        $cachedAccessToken = Cache::get($appid . self::ACCESS_TOKEN_KEY);
        if ($cachedAccessToken['access_token'] != $accessToken) {
            throw new Exception('access_token错误');
        }

        Cache::set($appid . self::TEMP_ACCESS_TOKEN_KEY, $accessToken, 300);
        return [
            'access_token'  => $accessToken,
            'refresh_token' => self::accessToken($appid, $secret, true),
            'expire_in'     => 7200
        ];
    }

    /**
     * 验证access_token
     * @param string $appid
     * @param string $secret
     * @param string $accessToken
     */
    public static function validateAccessToken(string $appid, string $accessToken)
    {
        if (!Cache::has($appid . self::ACCESS_TOKEN_KEY) || !Cache::has($appid . self::TEMP_ACCESS_TOKEN_KEY)) {
            throw new Exception('access_token已过期');
        }

        if (
            $accessToken === Cache::get($appid . self::ACCESS_TOKEN_KEY) ||
            $accessToken === Cache::get($appid . self::TEMP_ACCESS_TOKEN_KEY)
        ) {
            return true;
        }
        return false;
    }

    /**
     * 获取用户登录时使用的设备
     * @return string
     */
    public static function Os(): string
    {

        $agent = strtolower($_SERVER['HTTP_USER_AGENT']);

        if (strpos($agent, 'windows nt')) {
            $platform = 'windows';
        } elseif (strpos($agent, 'macintosh')) {
            $platform = 'mac';
        } elseif (strpos($agent, 'ipod')) {
            $platform = 'ipod';
        } elseif (strpos($agent, 'ipad')) {
            $platform = 'ipad';
        } elseif (strpos($agent, 'iphone')) {
            $platform = 'iphone';
        } elseif (strpos($agent, 'android')) {
            $platform = 'android';
        } elseif (strpos($agent, 'unix')) {
            $platform = 'unix';
        } elseif (strpos($agent, 'linux')) {
            $platform = 'linux';
        } else {
            $platform = 'other';
        }

        return $platform;
    }

    /**
     * 获取手机品牌
     * @param $agent
     * @return string
     */
    public static function client($agent): string
    {
        if (preg_match('/iPhone\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = 'iphone';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/SAMSUNG|Galaxy|GT-|SCH-|SM-\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '三星';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/Huawei|Honor|H60-|H30-\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '华为';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/Mi note|mi one\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '小米';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/HM NOTE|HM201\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '红米';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/Coolpad|8190Q|5910\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '酷派';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/ZTE|X9180|N9180|U9180\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '中兴';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/OPPO|X9007|X907|X909|R831S|R827T|R821T|R811|R2017|PBEM00|PACM00\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = 'OPPO';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/HTC|Desire\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = 'HTC';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/Nubia|NX50|NX40\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '努比亚';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/M045|M032|M355\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '魅族';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/Gionee|GN\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '金立';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/HS-U|HS-E\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '海信';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/Lenove\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '联想';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/ONEPLUS\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '一加';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/vivo\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = 'vivo';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/K-Touch\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '天语';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/DOOV\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '朵唯';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/GFIVE\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '基伍';
            $mobile_ver = $regs[0];
        } elseif (preg_match('/Nokia\s([^\s|;]+)/i', $agent, $regs)) {
            $mobile_brand = '诺基亚';
            $mobile_ver = $regs[0];
        } else {
            $mobile_brand = '其他';
            $mobile_ver = '';
        }
        $re_arr = array();
        $re_arr['mobile_brand'] = $mobile_brand;
        $re_arr['mobile_ver'] = $mobile_ver;
        return implode(' ', $re_arr);
    }

}
